﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Flurl.Http;
using Pay.Core;
using Pay.DTO;
using Pay.IService;
using Pay.TO;

namespace Pay.Service {
    public class LtdPayService : ServiceBase2, IPayService, IDisposable {
        private IUnitOfWork _iUnitOfWork;
        private ISettingService _iSettingService;
        private IMerchantService _iMerchantService;
        private IChargeService _iChargeService;
        private IProfitDayService _iProfitDayService;
        private IBillService _iBillService;
        private IPayHtmlService _iPayHtmlService;
        private IRegionService _iRegionService;
        private IPayNotifyService _iPayNotifyService;
        private LtdPaySign _ltdPaySign;

        public LtdPayService(IUnitOfWork iUnitOfWork, ISettingService iSettingService, IPayNotifyService iPayNotifyService,
                                        IMerchantService iMerchantService, IChargeService iChargeService,
                                        IProfitDayService iProfitDayService, IBillService iBillService,
                                        IPayHtmlService iPayHtmlService, IRegionService iRegionService) : base(iUnitOfWork) {
            _iUnitOfWork = iUnitOfWork;
            _iSettingService = iSettingService;
            _iMerchantService = iMerchantService;
            _iChargeService = iChargeService;
            _iProfitDayService = iProfitDayService;
            _iBillService = iBillService;
            _iPayHtmlService = iPayHtmlService;
            _iRegionService = iRegionService;
            _iPayNotifyService = iPayNotifyService;
            _ltdPaySign = new LtdPaySign();
        }

        public Task<transfer_result> AgencyFund(apply_receive model) {
            throw new NotImplementedException();
        }

        public Task<certify_verify_result> CertifyVerify(certify_verify model) {
            throw new NotImplementedException();
        }

        public int DealItp(long id) {
            throw new NotImplementedException();
        }

        public Task<gateway_pay_result> GatewayPay(gateway_pay_model model) {
            throw new NotImplementedException();
        }

        public List<type_setting> GatewayPayBank() {
            throw new NotImplementedException();
        }

        public Task<pay_notity> GatewayPayQuery(refund_model_query model) {
            throw new NotImplementedException();
        }

        public Task<refund_result> GatewayPayRefund(refund_model model) {
            throw new NotImplementedException();
        }

        public Task<refund_result> GatewayRefundQuery(refund_model_query model) {
            throw new NotImplementedException();
        }

        public Task<ApiResultMessage> InsteadReceive(verify_model_sms model) {
            throw new NotImplementedException();
        }

        public Task<ApiResultMessage> InsteadReceive(verify_model model) {
            throw new NotImplementedException();
        }

        public Task<int> ItpToFile(DateTime create_date) {
            throw new NotImplementedException();
        }

        public Task<mall_result> MallPay(mall_model obj) {
            throw new NotImplementedException();
        }

        public async Task<merchant_register_result> MerchantModify(long bind_id, string settle_type, PayChannel channel = PayChannel.None) {
            var binder = _iMerchantService.Get(bind_id);
            var oemer = _iMerchantService.Get(binder.oem_id.Value);
            var binder_payments = _iMerchantService.GetPayments(binder.id);
            var payment = binder_payments.FirstOrDefault(c => c.payment.channel == channel);
            var settle = payment.settles.First(c => c.settle_type == "T0" && c.code == "UNIONPAY");
            var auth_user = binder.setting.auth_info.ToDtoObject<merchant_register_model>();
			var merchantRegister = _iMerchantService.GetRegisterCode(auth_user.id_card, channel);
			var model = new ltd_merchant_register {
				bind_no = (merchantRegister == null ? "" : merchantRegister.MerchantNo),
				openid = (merchantRegister == null ? binder.openid : merchantRegister.OpenId),
				fee = settle.fee.ToString(),
				settle = ((int)(settle.settle * 100)).ToString(),
				account_name = auth_user.account_name,
				account_no = auth_user.account_no,
				branch_code = (string.IsNullOrEmpty(auth_user.branch_code) ? auth_user.bank_code : auth_user.branch_code),
				id_card = auth_user.id_card,
				mobile = auth_user.mobile
			};

            var resultApi = await _ltdPaySign.PayGateway<ltd_merchant_register_res>(model);
			if (resultApi != null && resultApi.result_code == 1000) {
				auth_user.pay_channel = channel;
				auth_user.reg_merchant_no = resultApi.merchant_no;
				auth_user.open_id = resultApi.openid;
				auth_user.bind_no = binder.merchant_no;
				auth_user.merchant_no = oemer.merchant_no;
				_iMerchantService.MerchantChannelRegister(auth_user);
				return ApiResultToJson.Json(new merchant_register_result { merchant_no = resultApi.merchant_no });
			}
            return ApiResultToJson.Json<merchant_register_result>("信息登记异常");
        }

        public async Task<merchant_register_result> MerchantRegister(merchant_register_model dto, string opt) {
            ltd_merchant_register_res resultApi = null;
            var user = _iMerchantService.Get(dto.bind_no);
			var auth_user = user.setting.auth_info;
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info("service：" + dto.pay_channel);
            if (opt == "A") {
				var merchantRegister = _iMerchantService.GetRegisterCode(dto.id_card, dto.pay_channel);
				if (merchantRegister == null) {
					var model = new ltd_merchant_register {
						openid = user.openid,
						fee = dto.fee.ToString(),
						settle = dto.settle,
						account_name = dto.account_name,
						account_no = dto.account_no,
						id_card = dto.id_card,
						mobile = dto.mobile,
						branch_code = (string.IsNullOrEmpty(dto.branch_code) ? auth_user.bank_code : dto.branch_code)
					};
                    resultApi = await _ltdPaySign.PayGateway<ltd_merchant_register_res>(model);
                    if (resultApi.result_code == 1000 || resultApi.result_code == 7000) {
                        dto.reg_merchant_no = resultApi.merchant_no;
						dto.open_id = resultApi.openid;
                        _iMerchantService.MerchantChannelRegister(dto);
                    }
                }
            } else {
                resultApi = await UpdateChannel(dto);
            }
            return ApiResultToJson.Json<merchant_register_result>("信息登记异常");
        }

        private async Task<ltd_merchant_register_res> UpdateChannel(merchant_register_model dto) {
			var merchantRegister = _iMerchantService.GetRegisterCode(dto.id_card, dto.pay_channel);
            ltd_merchant_register_res resultApi = null;
            var log = IocHelper.Get<ILogHelper>("info");
            var model = new ltd_merchant_register {
				bind_no = merchantRegister.MerchantNo,
				openid = merchantRegister.OpenId,
                fee = dto.fee.ToString(),
                settle = dto.settle,
                account_name = dto.account_name,
                account_no = dto.account_no,
                branch_code = dto.branch_code,
                id_card = dto.id_card,
                mobile = dto.mobile
            };
            resultApi = await _ltdPaySign.PayGateway<ltd_merchant_register_res>(model);
            log.Info(resultApi.result_code == 1000 ? "修改结算卡成功" : "进件失败");
            return resultApi;
        }

        public Task<merchant_register_result> MerchantRegister(long bind_id, string settle_type, PayChannel channel = PayChannel.None) {
            throw new NotImplementedException();
        }

        public Task<native_result> NativePay(native_model obj) {
            throw new NotImplementedException();
        }

        public async Task<string> Notify(string merchant_no, string order_no) {
            string result = string.Empty;
            charge_dto order = _iChargeService.Get(merchant_no, order_no);
            try {
                var data = new pay_notity {
                    tran_amount = ((int)(order.order_amount * 100)).ToString(), order_no = order.order_no, transaction_no = order.pay_info.transaction_no,
                    pay_time = order.pay_info.pay_time.HasValue ? order.pay_info.pay_time.Value : order.order_time,
                    status = (order.status == ChargeStatus.Finish ? 1 : 2)
                };
                data.result_msg = (data.status == 1 ? "支付成功" : order.fail);
                if (string.IsNullOrEmpty(order.notify)) return "OK";
                var notify_result = await order.notify.PostJsonAsync(ApiResultToJson.Json(data)).ReceiveJson<ResultMessage<string>>();
                result = notify_result.data;
                var log = IocHelper.Get<ILogHelper>("info");
                log.Info(order.order_no + ":" + notify_result.ToJson());
            } catch (Exception ex) {
                var log = IocHelper.Get<ILogHelper>("info");
                log.Error("订单通道查询异常:" + order.order_no);
                string message = string.Format("消息类型：{0}\r\n消息内容：{1}\r\n引发异常的方法：{2}\r\n引发异常源：{3}"
                                , ex.GetType().Name, ex.Message, ex.TargetSite, ex.Source + ex.StackTrace);
                log.Error(message);
            }
            return result;
        }

        public Task<string> NotifyTransfer(string merchant_no, string order_no) {
            throw new NotImplementedException();
        }

        public Task<quick_pay_result> QuickPay(quick_sms_model model) {
            throw new NotImplementedException();
        }

        public async Task<quick_pay_result> QuickPay(quick_pay_model model) {
            var log = IocHelper.Get<ILogHelper>("info");
            var binder = _iMerchantService.Get(model.bind_no);
			var auth_user = binder.setting.auth_info;
            var setting = _iSettingService.Get();
            //把商户请求转为通道请求消息
            var notify = setting.site.api_url + "/pay/ltd_pay_notify";
			var merchantRegister = _iMerchantService.GetRegisterCode(auth_user.id_card,model.pay_channel);
			if (merchantRegister == null) {
				log.Info(string.Format("商户号：{0}未进件", model.bind_no));
                return ApiResultToJson.Json<quick_pay_result>("商户未进件");
            }
            string pay_code = model.pay_code;
            model.settle_type = "T0";
            var binder_payments = _iMerchantService.GetPayments(binder.id);
            var payment = binder_payments.FirstOrDefault(c => c.payment.channel == model.pay_channel);
            var settle = payment.settles.First(c => c.settle_type == model.settle_type && c.code == pay_code);
            if (model.settle_fee / 100M != settle.settle)
                return ApiResultToJson.Json<quick_pay_result>("结算费与商户进件的结算费不同");
            if (model.fee != settle.fee)
                return ApiResultToJson.Json<quick_pay_result>("费率与商户进件的费率不同");
            if (model.pay_fee_amount != (int)Math.Ceiling(decimal.Parse(model.tran_amount) * model.fee))
                return ApiResultToJson.Json<quick_pay_result>("实扣费率金额不正确");

            var reg_query = new ltd_merchant_reg_query {
				bind_no = merchantRegister.MerchantNo
            };
            var queryApi = await _ltdPaySign.PayGateway<ltd_merchant_reg_query_res>(reg_query);
            if (queryApi.result_code != 1000) {
                log.Info(queryApi.result_msg);
                return ApiResultToJson.Json<quick_pay_result>("查询接口失败");
            }
			if (queryApi.fee != model.fee.ToString() || queryApi.account_no != auth_user.account_no || queryApi.settle != model.settle_fee.ToString()) {
				var updateFee = new ltd_merchant_register {
					bind_no = merchantRegister.MerchantNo,
					openid = queryApi.openid,
					fee = model.fee.ToString(),
					account_no = auth_user.account_no,
					mobile = auth_user.mobile,
					account_name = auth_user.account_name,
					id_card = auth_user.id_card,
					branch_code = (string.IsNullOrEmpty(auth_user.branch_code) ? auth_user.bank_code : auth_user.branch_code),
					settle = model.settle_fee.ToString()
				};
                var updateFeeApi = await _ltdPaySign.PayGateway<ltd_merchant_register_res>(updateFee);
                if (updateFeeApi.result_code != 1000) {
                    log.Info(updateFeeApi.result_msg);
                    return ApiResultToJson.Json<quick_pay_result>("修改商户进件接口失败");
                }
            }

            var charge = _iChargeService.AddByQuickPay(model);
            var card_info = new ltd_card_info {
                account_name = model.account_name,
                account_no = model.account_no,
                bank_code = model.bank_code,
                id_card = model.id_card,
				mobile = auth_user.mobile,
                fee = model.fee.ToString(),
                settle_fee = model.settle_fee.ToString(),
				pay_fee_amount = ((int)((((decimal.Parse(model.tran_amount) / 100) * model.fee)).RoundUp(2)*100M)).ToString()
            };
            var pay_info = new ltd_merchant_pay {
                bind_no = merchantRegister.MerchantNo,
                order_no = model.order_no,
                tran_amount = model.tran_amount,
                notify = notify,
                extra = card_info
            };
            var resultApi = await _ltdPaySign.PayGateway<ltd_merchant_pay_res>(pay_info);
            if (resultApi.result_code == 1000) {
                charge.plat_fee = Convert.ToDecimal(resultApi.fee);
                charge.plat_settle = Convert.ToDecimal((int.Parse(resultApi.settle) / 100));
                var ok = _iPayHtmlService.Save(new pay_html_dto {
                    id = model.order_no, merchant_no = model.merchant_no, order_no = model.order_no,
                    charge = charge.ToJson()
                });
                return ApiResultToJson.Json("鉴权成功，待确认支付", new quick_pay_result {
                    order_no = model.order_no, protocol_no = "", request_url = resultApi.request_url,
                    pay_time = DateTime.Now, transaction_no = "", status = 3
                });
            }
            return ApiResultToJson.Json<quick_pay_result>(resultApi.result_msg);
        }

        public Task<pay_notity> QuickPayQuery(refund_model_query model) {
            throw new NotImplementedException();
        }

        public Task<refund_result> QuickPayRefund(refund_model model) {
            throw new NotImplementedException();
        }

        public Task<refund_result> QuickPayRefundQuery(refund_model_query model) {
            throw new NotImplementedException();
        }

        public Task<ApiResultMessage> QuickPaySendsms(quick_sendsms_model model) {
            throw new NotImplementedException();
        }

        public Task<quota_result> Quota(string merchant_no, string busiType) {
            throw new NotImplementedException();
        }

        public Task<transfer_result> ReTransfer(long id) {
            throw new NotImplementedException();
        }

        public Task<batch_transfer_result> Transfer(batch_transfer model) {
            throw new NotImplementedException();
        }

        public Task<transfer_result> Transfer(apply_transfer model) {
            throw new NotImplementedException();
        }

        public Task<int> TransferBack(long batchId, string noticeTranId, long merchant_id) {
            throw new NotImplementedException();
        }

        public Task<int> TransferNotify(long batchId, string batchFileName, long merchant_id) {
            throw new NotImplementedException();
        }

        public Task<transfer_result> TransferQuery(transfer_query model) {
            throw new NotImplementedException();
        }

        public Task<transfer_result> TokenTransfer(long id) {
            throw new NotImplementedException();
        }

        public Task<transfer_result> TokenTransferQuery(transfer_query model) {
            throw new NotImplementedException();
        }
    }
}
